Imports System
Imports System.Text
Imports System.Data
Imports System.Collections.Generic
Imports System.Web
Imports System.IO

Imports Framework

'Collection Class (Customisable half)
Partial Public Class CProductTypeList

#Region "All"
    Private m_all As CProductType
    Public ReadOnly Property All As CProductType
        Get
            If IsNothing(m_all) Then
                SyncLock Me
                    If IsNothing(m_all) Then
                        m_all = New CProductType
                        m_all.TypeName = "All"
                    End If
                End SyncLock
            End If
            Return m_all
        End Get
    End Property

    Private m_plusAll As CProductTypeList
    Public ReadOnly Property PlusAll As CProductTypeList
        Get
            If IsNothing(m_plusAll) Then
                SyncLock Me
                    If IsNothing(m_plusAll) Then
                        m_plusAll = New CProductTypeList(Me.Count + 1)
                        m_plusAll.AddRange(Me)
                        m_plusAll.Add(All)
                    End If
                End SyncLock
            End If
            Return m_plusAll
        End Get
    End Property
#End Region

#Region "Filters"
    Public Function HavingProducts() As CProductTypeList
        Dim list As New CProductTypeList(Me.Count)
        For Each i As CProductType In Me
            If i.Products.Count > 0 Then list.Add(i)
        Next
        Return list
    End Function
#End Region

#Region "Aggregation"
    Private m_names As List(Of String)
    Public ReadOnly Property Names As List(Of String)
        Get
            If IsNothing(m_names) Then
                Dim temp As New List(Of String)(Me.Count)
                For Each i As CProductType In Me
                    temp.Add(i.Plural)
                Next
                m_names = temp
            End If
            Return m_names
        End Get
    End Property
#End Region

#Region "Searching (Optional)"
    'Represents a simple search box to search PK and any string columns (add overloads as required, based on the pattern below)
    'e.g. Public Function Search(ByVal nameOrId As String, ) As CProductTypeList
    Public Function Search(ByVal nameOrId As String) As CProductTypeList
        '1. Normalisation
        If IsNothing(nameOrId) Then nameOrId = String.Empty
        nameOrId = nameOrId.Trim.ToLower()
        
        '2. Start with a complete list
        Dim results As CProductTypeList = Me

        '3. Use any available index, such as those generated for fk/bool columns
        'Normal Case - non-unique index (e.g. foreign key)
        'If Integer.MinValue <> foreignKey Then results = results.GetByForeignKey(foreignKey)

        'Special case - unique index (e.g. primary key)
        If Not String.IsNullOrEmpty(nameOrId) Then
            'Dim id As Integer
            'If Integer.TryParse(nameOrId, id) Then
            '    Dim obj As CProductType = Me.GetById(id)
            '    If Not IsNothing(obj) Then
            '        results = New CProductTypeList(1)
            '        results.Add(obj)
            '        return results
            '    End If
            'End If
        End If
        
        '4. Exit early if remaining (non-index) filters are blank
        If String.IsNullOrEmpty(nameOrId) Then Return results
        
        '5. Manually search each record using custom match logic, building a shortlist
        Dim shortList As New CProductTypeList
        For Each i As CProductType In results
            If Match(nameOrId, i) Then shortList.Add(i)
        Next
        Return shortList
    End Function
    'Manual Searching e.g for string-based columns i.e. anything not indexed (add more params if required)
    Private Function Match(ByVal name As String, ByVal obj As CProductType) As Boolean
        If Not String.IsNullOrEmpty(name) Then
            If Not IsNothing(obj.TypeName) AndAlso obj.TypeName.ToLower().Contains(name) Then Return True
            Return False 'If filter is active, reject any items that dont match
        End If
        Return True 'No active filters (should catch this in step #4)
    End Function
#End Region

#Region "Cloning"
    Public Function Clone(ByVal target As CDataSrc) As CProductTypeList ', parentId As Integer) As CProductTypeList
        'No Transaction
        If TypeOf target Is CDataSrcRemote Then Return Clone(target, Nothing) ', parentId)

        'Transaction
        Dim cn As IDbConnection = target.Local.Connection()
        Dim tx As IDbTransaction = cn.BeginTransaction()
        Try
            Clone = Clone(target, tx) ', parentId)
            tx.Commit()
        Catch
            tx.Rollback()
            Throw
        Finally
            cn.Close()
        End Try
    End Function
    Public Function Clone(target as CDataSrc, txOrNull as IDbTransaction) As CProductTypeList ', parentId As Integer) As CProductTypeList
        Dim list As New CProductTypeList(Me.Count)
        For Each i As CProductType In Me
            list.Add(i.Clone(target, txOrNull))  ', parentId))    *Child entities must reference the new parent
        Next
        Return list
    End Function
#End Region

#Region "Export to Csv"
    'Web - Need to add a project reference to System.Web, or comment out these two methods
    Public Sub ExportToCsv(ByVal response As HttpResponse)
        ExportToCsv(response, "ProductTypes.csv")
    End Sub
    Public Sub ExportToCsv(ByVal response As HttpResponse, ByVal fileName As String)
        CDataSrc.ExportToCsv(response, fileName) 'Standard response headers
        Dim sw As New StreamWriter(response.OutputStream)
        ExportToCsv(sw)
        sw.Flush()
        response.End()
    End Sub

    'Non-web
    Public Sub ExportToCsv(ByVal filePath As String)
        Dim sw As New StreamWriter(filePath)
        ExportToCsv(sw)
        sw.Close()
    End Sub

    'Logic
    Protected Sub ExportToCsv(ByVal sw As StreamWriter)
        Dim headings As String() = New String() {"TypeId", "TypeName"}
        CDataSrc.ExportToCsv(headings, sw)
        For Each i As CProductType In Me
            Dim data As Object() = New Object() {i.TypeId, i.TypeName}
            CDataSrc.ExportToCsv(data, sw)
        Next
    End Sub
#End Region

End Class
